package siruna.WE.rendering;

import java.io.FileInputStream;
import java.util.HashMap;

import org.w3c.dom.Document;

import siruna.WE.DeviceInfo;
import siruna.WE.Global;
import siruna.WE.R;
import siruna.WE.FileManager.FileManager;
import siruna.WE.FileManager.WidgetConfig;
import siruna.WE.core.XML.XmlReader;
import siruna.WE.rendering.ListView.IconifiedText;
import siruna.WE.rendering.ListView.IconifiedTextListAdapter;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;

/**
 * Klasse gebruikt om het overzicht van de geinstalleerde widgets weer te geven
 * 
 * @author Tim
 * 
 */
public class OverView extends Activity {
	// lijst met de iconen
	HashMap<String, Bitmap> icons;
	// eigfenschappen van het toestel (hardware)
	DeviceInfo di;
	// geeft de naam van de widget die nu gesecteerd is
	protected String geselecteerd;
	// filemanager
	private FileManager fm;

	// textveld bovenaan
	private TextView tv;
	// xml reader
	private XmlReader xmlParser;
	// adapter om de lijst correct te tonen
	private IconifiedTextListAdapter itla;
	// lijst object
	private ListView lv;
	// boolean om aan te geven of je op dit moment de infoview toont
	private boolean in_Info = false;
	// layout van het scherm
	private LinearLayout ll;

	/**
	 * Wordt opgeroepen wanneer de activiteit voor het eerst aangemaakt wordt
	 */
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// setContentView(R.layout.);
		setContentView(R.layout.overview);
		di = new DeviceInfo(this);

		fm = new FileManager(this);
		xmlParser = new XmlReader();
		// RelativeLayout rl = (RelativeLayout) findViewById(R.id.overviewRL);

		ll = new LinearLayout(this);

		tv = (TextView) findViewById(R.id.TextView01);

		lv = new ListView(this);
		lv.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
				LayoutParams.FILL_PARENT));
		icons = fm.getIcons();

		itla = new IconifiedTextListAdapter(this);

		lv.setOnItemClickListener(new OnItemClickListener() {

			public void onItemClick(AdapterView<?> parent, View v,
					int position, long id) {
				// als je op een widget klikt, dan de widget opstarten
				geselecteerd = (String) v.getTag();
				if (!checkNetworkConnection()) {
					openWidgetConnectionDialog(geselecteerd).show();
				} else {
					startWidget(geselecteerd);
				}

			}

		});
		lv.setOnItemSelectedListener(new OnItemSelectedListener() {
			// gebruikt om de geselcteerde widget te bewaren
			public void onItemSelected(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {
				geselecteerd = (String) arg1.getTag();
			}

			public void onNothingSelected(AdapterView<?> arg0) {
				geselecteerd = "";

			}
		});

		buildListView();

	}

	/**
	 * Toon de lijst met iconen en namen
	 */
	private void buildListView() {
		in_Info = false;
		icons = fm.getIcons();

		itla.removeAll();
		if (icons.keySet().size() != 0) {
			for (String name : icons.keySet()) {
				BitmapDrawable bd = new BitmapDrawable(icons.get(name));

				itla.addItem(new IconifiedText(name, bd));
			}

			lv.setAdapter(itla);

			ll.removeAllViews();
			ll.setOrientation(LinearLayout.VERTICAL);
			TextView t = new TextView(this);
			t.setText(R.string.main);
			ll.addView(t);
			ll.addView(lv);
			setContentView(ll);
		} else {
			TextView t = new TextView(this);
			t.setText(R.string.installeereerst);
			setContentView(t);
		}

	}

	/**
	 * Methode die ervoor zorgt dat de juiste opties zichtbaar zijn in het menu
	 */
	public boolean onPrepareOptionsMenu(Menu menu) {
		super.onPrepareOptionsMenu(menu);
		menu.clear();
		if (in_Info) {
			// de info wordt nu getoond
			menu.add(getString(R.string.exit));
			menu.add(getString(R.string.verwijder));
			menu.add(getString(R.string.start));
		} else if (geselecteerd != null && !geselecteerd.equals("")) {
			lv.getSelectedView().setBackgroundColor(Color.rgb(255, 194, 102));

			// er een image geselecteerd
			menu.add(getString(R.string.exit));
			menu.add(getString(R.string.install));
			menu.add(getString(R.string.verwijder));
			menu.add(getString(R.string.start));
			menu.add(getString(R.string.info));

		} else {
			// er geen image geselecteerd
			menu.add(getString(R.string.exit));
			menu.add(getString(R.string.install));

		}
		return true;
	}

	/**
	 * Methode die ervoor zorgt dat bij het sluiten van de options menu, de
	 * geselecteerde widget terug een normaal achtergrondkleur krijgt
	 */
	@Override
	public void onOptionsMenuClosed(Menu menu) {
		super.onOptionsMenuClosed(menu);
		if (lv.getSelectedView() != null) {
			lv.getSelectedView().setBackgroundColor(Color.TRANSPARENT);
		}
	}

	/**
	 * Zorg dat de juiste handelingen worden uitgevoerd bij het selecteren van
	 * een optie
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		super.onOptionsItemSelected(item);

		if (lv.getSelectedView() != null) {
			lv.getSelectedView().setBackgroundColor(Color.TRANSPARENT);
		}
		if (item.getTitle().equals(getString(R.string.exit))) {
			this.setResult(Global.SUBACTIVITY_RESULTCODE_CHAINCLOSE);
			this.finish();
		} else if (item.getTitle().equals(getString(R.string.start))) {
			String s = (geselecteerd);

			
			if (!checkNetworkConnection()) {
				openWidgetConnectionDialog(s).show();
			} else {
				startWidget(s);
			}

		} else if (item.getTitle().equals(getString(R.string.verwijder))) {
			final String s = (geselecteerd);
			Dialog d = removeDialog(s);
			d.show();
		} else if (item.getTitle().equals(getString(R.string.install))) {
			if (checkNetworkConnection()) {
				installDialog().show();
				// fm.installWidget("http://www.widgetengine.be/WidgetTesta.zip","Widget1");

			} else {
				connectionDialog().show();
			}
		} else if (item.getTitle().equals(getString(R.string.info))) {
			FileInputStream config = fm.getConfigFileInputStream(geselecteerd);
			if (config != null) {
				Document doc = null;
				try {
					doc = xmlParser.parseFile(config);
					WidgetConfig wc = new WidgetConfig(doc);
					in_Info = true;
					setContentView(createInfoView(wc));
				} catch (Exception e) {
					Log.e("Error", "xmlParserException", e);
				}

			}
		}
		return true;
	}

	/**
	 * start de widget, sluit deze view af, de afhandeling gebeurt in de klasse
	 * Widgetengine2
	 * 
	 * @param s
	 */
	private void startWidget(String s) {
		Log.i("TEST", "widget "+s+" gestart");
		
		setResult(RESULT_OK, (new Intent()).putExtra("widgetId", s));
		finish();
	}

	/**
	 * dialoogvenster dat getoond wordt om te vragen of je een bepaalde widget
	 * zeker wilt verwijderen
	 * 
	 * @param s
	 *            naam van de widget die je wil verwijderen
	 * @return dialoogvenster
	 */
	private Dialog removeDialog(final String s) {
		Dialog d = new AlertDialog.Builder(this).setTitle(
				getString(R.string.opgelet)).setMessage(
				getString(R.string.zeker1) + " " + s + " "
						+ getString(R.string.zeker2)).setPositiveButton(
				getString(R.string.ok), new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {

						if (fm.removeWidget(s)) {

							if (fm.existsWidgetPreferences(s)) {
								Dialog d2 = removePreferencesDialog(s);
								d2.show();
							}
							buildListView();
							geselecteerd = "";
							tv.setText(R.string.overview);
						}
					}
				})

		.setNegativeButton(getString(R.string.cancel),
				new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {
					}
				}).create();
		return d;
	}

	/**
	 * dialoogvenster dat getoond wordt om te vragen of je van een bepaalde
	 * widget ook de preferences wilt verwijderen
	 * 
	 * @param s
	 *            naam van de widget die je wil verwijderen
	 * @return dialoogvenster
	 */
	private Dialog removePreferencesDialog(final String s) {
		Dialog d = new AlertDialog.Builder(this).setTitle(
				getString(R.string.opgelet)).setMessage(
				getString(R.string.zekerset1) + " " + s + " "
						+ getString(R.string.zekerset2)).setPositiveButton(
				getString(R.string.ok), new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {

						fm.removeWidgetPreferences(s);
					}
				})

		.setNegativeButton(getString(R.string.cancel),
				new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {
						/* User clicked Cancel so do some stuff */
					}
				}).create();
		return d;
	}

	/**
	 * Dialoogvenster dat een waarschuwing geeft dat er een lijst wordt
	 * opgehaalde van de server, dit kan even duren
	 * 
	 * @return dialoogvenster
	 */
	private Dialog installDialog() {
		Dialog d = new AlertDialog.Builder(this).setTitle(
				getString(R.string.opgelet)).setMessage(
				getString(R.string.installdialog)).setPositiveButton("Ok",
				new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {
						Intent i = new Intent(getApplicationContext(),
								installView.class);
						startActivityForResult(i, Global.INSTALLVIEW);
					}
				})

		.setNegativeButton(getString(R.string.cancel),
				new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {
					}
				}).create();
		return d;
	}

	/**
	 * Dialoogvenster dat een waarschuwing geeft bij het overgaan naar de
	 * install view. Er moet namelijk een verbinding zijn met het net.
	 * 
	 * @return dialoogvenster
	 */
	private Dialog connectionDialog() {
		Dialog d = new AlertDialog.Builder(this).setTitle(
				getString(R.string.opgelet)).setMessage(
				getString(R.string.connectiondialog)).setPositiveButton(
				getString(R.string.ok), new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {
						installDialog().show();
					}
				})

		.setNegativeButton(getString(R.string.cancel),
				new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {
					}
				}).create();
		return d;
	}

	/**
	 * Dialoogvenster dat een waarschuwing geeft bij het openen van een
	 * widget.Het kan namelijk nodig zijn een verbinding te hebben met het net.
	 * 
	 * @return dialoogvenster
	 */
	private Dialog openWidgetConnectionDialog(final String s) {
		Dialog d = new AlertDialog.Builder(this).setTitle(
				getString(R.string.opgelet)).setMessage(
				getString(R.string.openwidgetconnectiondialog))
				.setPositiveButton(getString(R.string.ok),
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog,
									int whichButton) {
								startWidget(s);
							}
						})

				.setNegativeButton(getString(R.string.cancel),
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog,
									int whichButton) {
							}
						}).create();
		return d;
	}

	/**
	 * bouw de view op die de info van de widget toont
	 * 
	 * @param wc
	 *            het object dat de info bevat
	 * @return android view
	 */
	private View createInfoView(WidgetConfig wc) {
		LinearLayout ll = new LinearLayout(this);

		ll.setOrientation(LinearLayout.VERTICAL);
		TextView tv = new TextView(this);
		tv.setText(wc.toString());

		Button b = new Button(this);
		b.setText(R.string.terug);

		b.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				in_Info = false;
				leaveInfoView();
			}
		});

		ll.addView(tv);
		ll.addView(b);
		return ll;

	}

	/**
	 * methode om de info view te verlaten
	 */
	private void leaveInfoView() {
		setContentView(R.layout.overview);
		geselecteerd = "";
		buildListView();
	}

	/**
	 * methode die wordt aangeroepen tekens wanneer een sub activity sluit.
	 */
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		switch (resultCode) {
		case Global.SUBACTIVITY_RESULTCODE_CHAINCLOSE:
			// sluiten !
			this.setResult(Global.SUBACTIVITY_RESULTCODE_CHAINCLOSE);
			this.finish();
			break;
		}
		if (requestCode == Global.INSTALLVIEW) {
			// als de install view sluit, de lijst opnieuw opbouwen
			buildListView();
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	/**
	 * knop indrukken opvangen, alleen als er o de return toets wordt gedrukt de
	 * view sluiten
	 */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			if (!in_Info) {
				this.setResult(Global.SUBACTIVITY_RESULTCODE_CHAINCLOSE);
				this.finish();
			} else {

				leaveInfoView();
			}
			return true;
		} else {
			return super.onKeyDown(keyCode, event);
		}
	}

	/**
	 * controleer of er een internetverbinding aanwezig is
	 * 
	 * @return true als er een verbinding is met het net, false indien niet
	 */
	private boolean checkNetworkConnection() {
		ConnectivityManager connec = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

		State mobile = connec.getNetworkInfo(0).getState();
		State wifi = connec.getNetworkInfo(1).getState();

		if (mobile == NetworkInfo.State.CONNECTED
				|| wifi == NetworkInfo.State.CONNECTED) {
			return true;

		} else {
			return false;
		}
	}
}